#!/usr/bin/env python3
import json
import os
import argparse
import sys
import datetime
import hashlib
import urllib.request
import urllib.parse
from urllib.error import URLError
from urllib.error import HTTPError
import ssl
import requests
import re

ssl._create_default_https_context = ssl._create_unverified_context

import AutoExecUtils


class FusionComputer:

    def __init__(self, ip, port, mgmt_port, username, password, isVerbose):
        self.ip = ip
        self.port = port
        self.mgmt_port = mgmt_port
        self.username = username
        self.password = password
        self.isVerbose = isVerbose
        self.serverBaseUrl = "https://{}:{}/".format(ip, port)

        self.apiMap = {
            "version": "service/versions",
            "auth": "service/session",
            "sites": "service/sites",
            "clusters": "{sites}/clusters",
            "hosts": "{sites}/hosts",
            "vms": "{sites}/vms",
            "datastores": "{sites}/datastores",
            "pnics": "{sites}/pnics",
            "storageresources": "{sites}/storageresources",
            "storageunits": "{sites}/storageunits/querybypage",
            "volumes": "{sites}/volumes",
            "alarms": "{sites}/alarms/activeAlarms",
        }

    def addHeaders(self, request, headers):
        for k, v in headers.items():
            request.add_header(k, v)

    def httpPOST(self, apiUri, authToken, params=None):
        url = self.serverBaseUrl + apiUri
        userAgent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)"
        headers = {"Content-Type": "application/x-www-form-urlencoded; charset=utf-8", "User-Agent": userAgent, "X-Auth-Token": authToken}
        if params != None:
            data = urllib.parse.urlencode(params)
            req = urllib.request.Request(url, bytes(data, "utf-8"))
        else:
            req = urllib.request.Request(url)
        self.addHeaders(req, headers)
        response = None
        try:
            response = urllib.request.urlopen(req)
        except HTTPError as ex:
            errMsg = ex.code
            if ex.code > 500:
                content = ex.read()
                errObj = json.loads(content)
                errMsg = errObj["Message"]
            print("ERROR::Request url:{} failed, {}".format(url, errMsg))
        except URLError as ex:
            print("ERROR::Request url:{} failed, {}\n".format(url, ex.reason))
        return response

    def httpGET(self, apiUri, authToken, params=None):
        url = self.serverBaseUrl + apiUri
        userAgent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)"
        headers = {"User-Agent": userAgent, "X-Auth-Token": authToken}
        if params != None:
            data = urllib.parse.urlencode(params)
            url = url + "?" + data
        # print("DEBUG::url is:{} and authToken is:{}\n".format(url,authToken))
        req = urllib.request.Request(url)
        self.addHeaders(req, headers)
        response = None
        try:
            response = urllib.request.urlopen(req)
        except HTTPError as ex:
            errMsg = ex.code
            if ex.code > 500:
                content = ex.read()
                errObj = json.loads(content)
                errMsg = errObj["Message"]
                print("ERROR: :Request url:{} failed, {}".format(url, errMsg))
        except URLError as ex:
            print("ERROR: :Request url:{} failed, {}".format(url, ex.reason))

        return response

    def httpJSON(self, apiUri, authToken, params=None):
        url = self.serverBaseUrl + apiUri
        userAgent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)"
        headers = {
            "Content-Type": "application/json; charset=utf-8",
            "User-Agent": userAgent,
            "X-Auth-Token": authToken,
        }

        req = urllib.request.Request(url, bytes(json.dumps(params), "utf-8"))
        self.addHeaders(req, headers)
        response = None
        try:
            response = urllib.request.urlopen(req)
        except HTTPError as ex:
            errMsg = ex.code
            if ex.code > 500:
                content = ex.read()
                errObj = json.loads(content)
                errMsg = errObj["Message"]
            print("ERROR: :Request url:{} failed, {}".format(url, errMsg))
        except URLError as ex:
            print("ERROR: :Request url:{} failed, {}".format(url, ex.reason))
        return response

    def sha256hex(self, password):
        sha256 = hashlib.sha256()
        sha256.update(password.encode())
        res = sha256.hexdigest()
        # print("DEBUG::sha256加密结果:", res)
        return res

    def auth(self):
        auth_key = self.sha256hex(self.password)
        url = self.serverBaseUrl + self.apiMap["auth"]
        userAgent = "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)"
        myheaders = {"Content-Type": "application/json; charset=utf-8", "User-Agent": userAgent, "X-Auth-User": self.username, "X-Auth-Key": auth_key, "version": "8.0", "X-Auth-UserType": "0"}
        req = requests.post(url, headers=myheaders, verify=False)
        token = None
        content = None
        try:
            response = req.content
            token = req.headers.get("X-Auth-Token")
            # print('DEBUG:: token:'.format(token))
        except HTTPError as ex:
            errMsg = ex.code
            if ex.code > 500:
                content = ex.read()
            print("ERROR:: Login authentication {} failed, {}".format(url, content))
        except URLError as ex:
            print("ERROR:: Login authentication {} failed, {}\n".format(url, ex.reason))
        self.authToken = token
        return token

    def getVersion(self):
        obj = {}
        obj["VENDOR"] = "Huawei"
        response = self.httpGET(self.apiMap["version"], self.authToken)
        if response is None:
            return obj

        """
        {
            "versions": [
                {
                    "loginUri": "/service/session",
                    "version": "v6.3"
                },
                {
                    "loginUri": "/service/session",
                    "version": "v6.5"
                }
            ]
        }
        """
        if response.status == 200:
            rs = json.loads(response.read())
            items = rs["versions"]
            for ver in items:
                obj["VERSION"] = ver["version"]
        else:
            print("ERROR:: Request FusionComputer get version failed .\n")
        return obj

    def getSites(self):
        sites = []
        response = self.httpGET(self.apiMap["sites"], self.authToken)
        if response is None:
            return sites

        """
        {
            "sites": [
                {
                    "ip": "10.10.101.227",
                    "isDC": false,
                    "isSelf": true,
                    "mgntNetworkType": "ipv4",
                    "name": "site123",
                    "status": "normal",
                    "uri": "/service/sites/389F07DF",
                    "urn": "urn:sites:389F07DF"
                }
            ]
        }
        """
        if response.status == 200:
            rs = json.loads(response.read())
            items = rs["sites"]
            for site in items:
                dc = {}
                dc["_OBJ_CATEGORY"] = "VIRTUALIZED"
                dc["_OBJ_TYPE"] = "VIRTUALIZED-DATACENTER"
                moid = site["urn"].split(":")[2]
                dc["MOID"] = moid
                dc["NAME"] = site["name"]
                dc["IP"] = site["ip"]
                dc["STATUS"] = site["status"]
                dc["URI"] = site["uri"]
                dc["URN"] = site["urn"]
                sites.append(dc)
        else:
            print("ERROR:: Request FusionComputer get sites failed .\n")
        return sites

    def getClusters(self, uri, dcName):
        clusters = []
        url = self.apiMap["clusters"]
        url = url.replace("{sites}", uri)
        response = self.httpGET(url, self.authToken)
        if response is None:
            return clusters
        """
        {
            "clusters": [
                {
                    "cpuResource": {
                        "allocatedSizeMHz": 13600,
                        "totalSizeMHz": 71400
                    },
                    "description": "额外付出",
                    "isAutoAdjustNuma": false,
                    "memResource": {
                        "allocatedSizeMB": 136932,
                        "realtimeUsedSizeMB": 136932,
                        "totalSizeMB": 166614
                    },
                    "name": "ManagementCluster",
                    "tag": "domain/default",
                    "uri": "/service/sites/389F07DF/clusters/117",
                    "urn": "urn:sites:389F07DF:clusters:117"
                }
            ]
        }
        """
        if response.status == 200:
            rs = json.loads(response.read())
            items = rs["clusters"]
            for cluster in items:
                clu = {}
                clu["_OBJ_CATEGORY"] = "VIRTUALIZED"
                clu["_OBJ_TYPE"] = "VIRTUALIZED-CLUSTER"
                moid = cluster["urn"].split(":")[4]
                clu["MOID"] = moid
                clu["VIRT_PLATFORM"] = "fusionCompute"
                clu["DC_NAME"] = dcName
                clu["NAME"] = cluster["name"]
                clu["TAG"] = cluster["tag"]
                clu["CPU_TOTALSIZE_MHZ"] = cluster["cpuResource"]["totalSizeMHz"]
                clu["CPU_ALLOCATEDSIZE_MHZ"] = cluster["cpuResource"]["allocatedSizeMHz"]
                clu["MEM_TOTALSIZE_MB"] = cluster["memResource"]["totalSizeMB"]
                clu["MEM_ALLOCATEDSIZE_MB"] = cluster["memResource"]["allocatedSizeMB"]
                clu["MEM_REALTIME_USEDSIZE_MB"] = cluster["memResource"]["realtimeUsedSizeMB"]
                clu["DESCRIPTION"] = cluster["description"]
                clu["URI"] = cluster["uri"]
                clu["URN"] = cluster["urn"]
                clu["DATASTORE"] = self.getDatastores(uri)
                # clu['STORAGE_UNITS'] = self.getStorageunits(uri)

                clusters.append(clu)
        else:
            print("ERROR:: Request FusionComputer get clusters failed .\n")
        return clusters

    def addHostSerialInfo(self, hosts):
        data = {"authUser": self.username, "authKey": self.password, "userType": "0", "authType": "0", "acceptLanguage": "zh-CN"}
        json_data = json.dumps(data).encode("utf-8")
        # api管理端口内采集不到sn信息，采用管理端口接口
        url = "https://{}:{}/service/login/form?login=login".format(ip, self.mgmt_port)
        headers = {"Content-Type": "application/json"}
        req = urllib.request.Request(url, data=json_data, headers=headers)
        response = urllib.request.urlopen(req)
        result = response.read().decode("utf-8")
        # print("DEBUG:: 8443 login result is {}".format(result))
        resHeaders = response.info()
        cookie = ""
        token = ""
        for header, value in resHeaders.items():
            print(header, value)
            if header == "Set-Cookie":
                cookie = value
            if header == "csrfToken":
                token = value

        if cookie == "" or token == "":
            return

        for host in hosts:
            urn = host["URN"]
            metric_data = [{"urn": urn, "metricId": ["product_serial", "product_name", "product_mfg", "cpu_info"]}]
            json_metric_data = json.dumps(metric_data).encode("utf-8")
            pattern = r"sites:(.*):hosts"
            match = re.search(pattern, urn)
            siteID = match.group(1)
            metric_url = "https://{}:{}/service/sites/{}/monitors/objectmetric-realtimedata?siteID={}".format(ip, 8443, siteID, siteID)
            metric_headers = {"Content-Type": "application/json", "Cookie": cookie, "CSRF-HW": token}
            metric_req = urllib.request.Request(metric_url, data=json_metric_data, headers=metric_headers)
            response = urllib.request.urlopen(metric_req)
            rs = json.loads(response.read())
            # print("DEBUG::8443 realtime rs is {}\n".format(rs))

            serial = rs["items"][0]["value"][0]["metricValue"]
            host["BOARD_SERIAL"] = serial
            host["MODEL"] = rs["items"][0]["value"][1]["metricValue"]
            host["MANUFACTURER"] = rs["items"][0]["value"][2]["metricValue"]
            cpuString = rs["items"][0]["value"][3]["metricValue"]
            cpuJson = json.loads(cpuString)
            host["CPU_MODEL"] = cpuJson[0]["version"]
            # host['PK'] = ["BOARD_SERIAL"]

    def getHosts(self, uri):
        hosts = []
        url = self.apiMap["hosts"]
        url = url.replace("{sites}", uri)
        response = self.httpGET(url, self.authToken)
        if response is None:
            return hosts
        """
       {
          "hosts":[
            {
              "urn":"urn:sites:414B07B7:hosts:175",
              "uri":"/service/sites/414B07B7/hosts/175",
              "uuid":"46e0aefc-42e5-4a4b-ac26-d12505f78706",
              "name":"hgcna121",
              "description":"",
              "ip":"10.244.250.121",
              "clusterUrn":"urn:sites:414B07B7:clusters:116",
              "clusterName":"HG_XC_CLUSTER",
              "status":"normal",
              "isMaintaining":false,
              "multiPathMode":"CURRENCY",
              "hostMultiPathMode":"CURRENCY",
              "memQuantityMB":1017982,
              "cpuQuantity":86,
              "nicQuantity":12,
              "cpuMHz":2600,
              "attachedISOVMs":[],
              "computeResourceStatics":"/service/sites/414B07B7/hosts/175/computeResourceStatics",
              "ntpIp1":"20.5.101.10",
              "ntpIp2":"20.5.101.9",
              "ntpIp3":"",
              "ntpCycle":64,
              "physicalCpuQuantity":2,
              "gpuCapacity":-1,
              "gpuCapacityReboot":-1,
              "gdvmMemoryReboot":128,
              "gsvmMemoryReboot":128,
              "maxImcSetting":"Kunpeng-920",
              "isFailOverHost":false,
              "clusterEnableIOTailor":false,
              "hostRealName":"hgcna121",
              "cpuResource":{
                "totalSizeMHz":223600,
                "allocatedSizeMHz":20800,
                "manageCPUs":"0,1,2,3,4,5,6,7,8,9",
                "emulatorCPUs":""
              },
              "memResource":{
                "totalSizeMB":1017982,
                "allocatedSizeMB":966535,
                "realtimeUsedSizeMB":966535
              },
              "memMuxRatio":"94.95",
              "cpuMuxRatio":"493.02"
            }
          ],
          "total":16
        }
       """
        if response.status == 200:
            rs = json.loads(response.read())
            items = rs["hosts"]
            for host in items:

                ins = {}
                ins["_OBJ_CATEGORY"] = "HOST"
                ins["_OBJ_TYPE"] = "HOST"
                moid = host["urn"].split(":")[4]
                ins["MOID"] = moid
                cpunum = int(host["physicalCpuQuantity"])
                cpuQuantity = int(host["cpuQuantity"])
                ins["CPU_CORES"] = cpuQuantity / cpunum
                ins["CPU_THREADS"] = cpuQuantity
                ins["CPU_NUM"] = cpunum
                ins["NAME"] = host["name"]
                ins["URI"] = host["uri"]
                ins["URN"] = host["urn"]
                memQuantityMB = host["memQuantityMB"]
                ins["MEM_MAXIMUM_CAPACITY"] = int(memQuantityMB / 1024)
                ins["IP"] = host["ip"]
                ins["HOST_IP"] = host["ip"]
                ins["MGMT_IP"] = host["ip"]
                ins["UUID"] = host["uuid"]
                ins["CLUSTERURN"] = host["clusterUrn"]
                ins["CLUSTERNAME"] = host["clusterName"]
                ins["ISMAINTAINING"] = host["isMaintaining"]
                ins["ISFAILOVERHOST"] = host["isFailOverHost"]
                ins["STATUS"] = host["status"]
                ins["NICQUANTITY"] = host["nicQuantity"]
                data_list = []
                net_list = self.getHostPNics(host["uri"])
                if net_list != None:
                    for net in net_list:
                        data_list.append(net)
                ins["ETH_INTERFACES"] = data_list
                hosts.append(ins)
        else:
            print("ERROR:: Request FusionComputer get hosts failed .\n")

        self.addHostSerialInfo(hosts)
        return hosts

    def getHostPNics(self, uri):
        pnics = []
        url = self.apiMap["pnics"]
        url = url.replace("{sites}", uri)
        url = url + "?limit=100&offset=0"
        response = self.httpGET(url, self.authToken)
        if response is None:
            return

        elif response.status == 200:
            rs = json.loads(response.read())
            items = rs["pnics"]
            total = rs["total"]
            print("INFO:: total find {} count pnics.".format(total))
            for pnic in items:
                pnics.append(pnic)
        else:
            print("ERROR:: Request FusionComputer get pnics failed .\n")

        return pnics

    def getVms(self, uri, hosts):
        vms = []
        url = self.apiMap["vms"]
        url = url.replace("{sites}", uri)
        url = url + "?limit=100&offset="
        offset = 0
        # 默认限制每页查询100

        self.getVmsLoop(url, offset, vms, hosts)
        return vms

    def getVmsLoop(self, url, offset, allVms, hosts):
        response = self.httpGET(url + str(offset), self.authToken)
        """
       {
          "urn":"urn:sites:414B07B7:vms:i-00000447",
          "uri":"/service/sites/414B07B7/vms/i-00000447",
          "uuid":"2c93afb7-053e-41bd-bdb7-05ddcef3dc2e",
          "name":"10.244.37.41_app1",
          "arch":"arm",
          "description":"",
          "location":"urn:sites:414B07B7:clusters:116",
          "locationName":"HG_XC_CLUSTER",
          "hostUrn":"urn:sites:414B07B7:hosts:26571",
          "clusterUrn":"urn:sites:414B07B7:clusters:116",
          "status":"running",
          "pvDriverStatus":"running",
          "toolInstallStatus":"empty",
          "cdRomStatus":"empty",
          "isTemplate":false,
          "isLinkClone":false,
          "createTime":"2024-04-12 08:18:55",
          "idle":-1,
          "toolsVersion":"3.0.602.001",
          "isBindingHost":false,
          "hostName":"hgcna134",
          "clusterName":"HG_XC_CLUSTER",
          "hugePage":"4K",
          "params":{
            "snapshotNum":"0"
          },
          "vmType":0,
          "drStatus":9,
          "rpoStatus":0,
          "initSyncStatus":0,
          "vmConfig":{
            "nics":[
              {
                "mac":"28:6e:d4:89:66:72",
                "ip":"10.244.37.41",
                "ipList":"10.244.37.41",
                "sequenceNum":0,
                "ips6":[]
              }
            ],
            "properties":{
              "secureVmType":"",
              "dpiVmType":""
            },
            "numaNodes":0
          },
          "minCompatibleimcSetting":"Kunpeng-920",
          "objectPrivs":[]
        }
       """
        if response is None:
            return
        elif response.status == 200:
            rs = json.loads(response.read())
            items = rs["vms"]
            total = rs["total"]
            print("INFO:: total find {} count vms.".format(total))
            for vm in items:
                ins = {}
                osType = "Linux"
                if vm["vmType"] != 0:
                    osType = "Windows"
                ins["_OBJ_CATEGORY"] = osType
                moid = vm["urn"].split(":")[4]
                ins["VM_ID"] = moid
                ins["NAME"] = vm["name"]
                ins["URI"] = vm["uri"]
                ins["URN"] = vm["urn"]
                ins["OS_TYPE"] = osType
                ins["UUID"] = vm["uuid"]
                ins["DESCRIPTION"] = vm["description"]
                ins["STATUS"] = vm["status"]
                ins["CREATETIME"] = vm["createTime"]
                nics = vm["vmConfig"]["nics"]
                for nic in nics:
                    ip = nic["ip"]
                    ins["IP"] = ip
                    break

                # 与物理机的关系
                for host in hosts:
                    if host["URN"] == vm["hostUrn"]:
                        ins["HOST_ON"] = [{"_OBJ_CATEGORY": "HOST", "_OBJ_TYPE": "HOST", "HOST_IP": host["IP"], "BOARD_SERIAL": host["BOARD_SERIAL"], "UUID": host["UUID"]}]

                allVms.append(ins)

            if len(allVms) < total:
                offset = offset + len(items)
                self.getVmsLoop(url, offset, allVms, hosts)

        else:
            print("ERROR:: Request FusionComputer get vms failed .\n")

        return

    def getDatastores(self, uri):
        datastores = []
        url = self.apiMap["datastores"]
        url = url.replace("{sites}", uri)
        response = self.httpGET(url, self.authToken)
        if response is None:
            return datastores
        """
        {
            "datastores": [
                {
                    "actualCapacityGB": 482,
                    "actualFreeSizeGB": 263,
                    "capacityGB": 482,
                    "clusterSize": 1024,
                    "dsLockType": 0,
                    "freeSizeGB": 263,
                    "hosts": [
                        "urn:sites:389F07DF:hosts:177"
                    ],
                    "isThin": true,
                    "name": "autoDS_CNA001",
                    "refreshTime": "2020-05-09 01:28:43",
                    "status": "NORMAL",
                    "storageType": "LOCALPOME",
                    "storageUnits": [
                        {
                            "sdName": "LOCAL",
                            "suName": "36c0111875d52a925255f83c609f0d08e",
                            "urn": "2F9C10B39BB545A39549DF00129AEBC7"
                        }
                    ],
                    "suIdList": [],
                    "suName": "36c0111875d52a925255f83c609f0d08e",
                    "suUrn": "urn:sites:389F07DF:storageunits:2F9C10B39BB545A39549DF00129AEBC7",
                    "thinRate": 100,
                    "uri": "/service/sites/389F07DF/datastores/1",
                    "urn": "urn:sites:389F07DF:datastores:1",
                    "usedSizeGB": 364
                }
            ]
        ]
        """
        if response.status == 200:
            rs = json.loads(response.read())
            items = rs["datastores"]
            for obj in items:
                ins = {}
                ins["_OBJ_CATEGORY"] = "VIRTUALIZED"
                ins["_OBJ_TYPE"] = "VIRTUALIZED-DATASTORE"
                urns = obj["urn"].split(":")
                ins["UNIQUE_NAME"] = obj["urn"]
                ins["MOID"] = urns[3] + "-" + urns[4]
                ins["NAME"] = obj["name"]
                suName = obj["suName"]
                if suName.find("scsi-") == 0:
                    suName = suName[5:]
                if suName.find("3") == 0:
                    suName = suName[1:]
                ins["SU_NAME"] = obj["suName"]
                ins["SU_UUID"] = suName
                ins["SU_URN"] = obj["suUrn"]
                ins["STATUS"] = obj["status"]
                ins["TYPE"] = obj["storageType"]
                capacity = int(obj["capacityGB"])
                available = int(obj["freeSizeGB"])
                used = capacity - available
                used_pct = round((used / capacity) * 100)
                ins["CAPACITY"] = capacity
                ins["AVAILABLE"] = available
                ins["USED"] = used
                ins["USED_PCT"] = used_pct
                ins["UNIT"] = "GB"
                ins["PATH"] = obj["urn"]
                ins["HOSTS"] = obj["hosts"]
                datastores.append(ins)
        else:
            print("ERROR:: Request FusionComputer get datastores failed .\n")
        return datastores

    def getVolumes(self, uri):
        volumes = []
        url = self.apiMap["volumes"]
        url = url.replace("{sites}", uri)
        url = url + "?limit=100&offset="
        offset = 0
        # 默认限制每页查询100
        self.getVolumesLoop(url, offset, volumes)
        return volumes

    def getVolumesLoop(self, url, offset, allVolumes):
        response = self.httpGET(url + str(offset), self.authToken)
        if response is None:
            return
        elif response.status == 200:
            rs = json.loads(response.read())
            items = rs["volumes"]
            total = rs["total"]
            print("INFO:: total find {} count volumes.".format(total))
            for volume in items:
                allVolumes.append(volume)

            if len(allVolumes) < total:
                offset = offset + len(items)
                self.getVolumesLoop(url, offset, allVolumes)

        else:
            print("ERROR:: Request FusionComputer get volumes failed .\n")

        return

    def getStorageunits(self, uri):
        storageunits = []
        url = self.apiMap["storageunits"]
        url = url.replace("{sites}", uri)
        url = url + "?limit=100&offset=0&deviceType=0"
        response = self.httpGET(url, self.authToken)
        if response is None:
            return storageunits
        """
        {
             "total":integer,
             "storageUnits ":[{
                 "urn":string,
                 "uri":string,
                 "sdUrn":string,
                 "sdId":integer,
                 "sdName":string,
                 "name":string,
                 "type":string,
                 "capacityGB":integer,
                 "status": string,
                 "refreshTime": string, // eg: 2012-08-27 20:29:19
                 "isThin": boolean,
                 "supportADL":integer,
                 "wwn":string,
                 "hostNum":integer,
                 "suHostID":integer,
                 "sanSN":string,
                 "suLunID":string,
                 "hostList":[{
                             "urn":string,
                             "hosName":string,
                             "clusterUrn":string,
                             "cluster":string,
                             "hostIp":string,
                             "status":string,
                             "refreshTime":string,
                             "folderUrn":string,
                             "folderName":string,
                             "hasDsOn":boolean,
                             "isMaintaining":boolean
                             }]
             }]
            }
        """
        if response.status == 200:
            rs = json.loads(response.read())
            print(rs)
            items = rs["storageUnits"]
            for obj in items:
                storageunits.append(obj)
        else:
            print("ERROR:: Request FusionComputer get storageunits failed .\n")
        return storageunits

    def getStorageresources(self, uri):
        storageresources = []
        url = self.apiMap["storageresources"]
        url = url.replace("{sites}", uri)
        url = url + "?limit=100&offset=0"
        response = self.httpGET(url, self.authToken)
        if response is None:
            return storageresources
        """
        { 
             "total":integer,
             "storageResources":[{
                 "urn":string, // urn:sites:1:storageresources:1
                 "uri":string, // service/sites/1/storageresources/1
                 "name":string, //可能为空
                 "storageType":string, 
                 "managementIp":string,
                 "managementPort":integer, //可能为空
                 "dataChannel":
                             [{
                             "ip":string,
                             "port":integer
                             }], //SAN,advancdSAN,NAS 有，FusionStorage 是空
                 "username":string,//可能为空
                 "vender":string,
                 "deviceType":string,
                 "iSCSITargetIQN":string,
                 "accessMode":integer,
                 "digest":integer, (KVM 未支持)
                 "accessMode":integer
                 }]
            }
        """
        if response.status == 200:
            rs = json.loads(response.read())
            print(rs)
            items = rs["storageResources"]
            for obj in items:
                storageresources.append(obj)
        else:
            print("ERROR:: Request FusionComputer get storageResources failed .\n")
        return storageresources

    def getAlarms(self, uri, alarms):
        url = self.apiMap["alarms"]
        url = url.replace("{sites}", uri)
        response = self.httpGET(url, self.authToken)
        if response is None:
            return alarms
        """
            {
                "total": 24,
                "updateFlag": 1,
                "viewId": 0,
                "pageno": 0,
                "itemSize": 24,
                "items": [
                    {
                        "iDisplay": "未屏蔽",
                        "dtArrivedTime": "1587961783079",
                        "dtOccurTime": "1587961802085",
                        "dtClearTime": "-",
                        "objectUrn": "urn:sites:389F07DF:vrms:2",
                        "svAdditionalInfo": "-",
                        "svAlarmName": "VRM未配置NTP时钟源",
                        "iSyncNo": 4,
                        "iParse": 0,
                        "svAlarmCause": "-",
                        "iAlarmCategory": "原始告警",
                        "svClearAlarmUserName": "-",
                        "objectType": "否",
                        "iClearType": "-",
                        "svMoc": "vrms",
                        "dtUpdateTime": "-",
                        "svLocationInfo": "-",
                        "iAlarmLevel": "重要",
                        "iAffectOpFlag": "不影响",
                        "iSerialNo": 3,
                        "svEventType": "业务质量事件",
                        "urnByName": "VRM02",
                        "svAlarmID": "15.1007019",
                        "iAutoClear": "是"
                    }
                ]
            }
        """
        if response.status == 200:
            rs = json.loads(response.read())
            items = rs["items"]
            for obj in items:
                alarm = {}
                alarm["KEY"] = obj["objectUrn"]
                alarm["NAME"] = obj["urnByName"]
                alarm["ENTITY"] = obj["svEventType"]
                alarm["STATUS"] = obj["iAlarmLevel"]
                alarm["TIME"] = datetime.strftime(datetime.fromtimestamp(obj["dtOccurTime"]), "%Y-%m-%d %H:%M:%S")
                alarm["MESSAGE"] = obj["svAlarmName"] + ":" + obj["svAdditionalInfo"]
                alarms.append(alarm)
        else:
            print("ERROR:: Request FusionComputer get alarms failed .\n")
        return alarms

    def collect(self):
        authToken = self.auth()
        datas = []
        data = {}

        if authToken is None:
            return data

        data = self.getVersion()
        data["MGMT_IP"] = self.ip
        data["MGMT_PORT"] = self.port
        data["_OBJ_CATEGORY"] = "VIRTUALIZED"
        data["_OBJ_TYPE"] = "FUSIONCOMPUTER"
        data["VIRT_PLATFORM"] = "fusionCompute"
        data["PK"] = ["MGMT_IP"]

        # 数据中心(资源池)
        sites = self.getSites()
        newsites = []
        alarms = []
        for site in sites:
            uri = site["URI"]
            dcName = site["NAME"]
            # urn = site['URN']
            # 集群
            clusters = self.getClusters(uri, dcName)
            site["CLUSTER"] = clusters

            # 物理机
            hosts = self.getHosts(uri)
            datas.extend(hosts)

            # 虚拟机
            vms = self.getVms(uri, hosts)
            datas.extend(vms)

            for cluster in clusters:
                rel_host = []
                for host in hosts:
                    if host["CLUSTERNAME"] == cluster["NAME"]:
                        rel_host.append({"_OBJ_CATEGORY": "HOST", "_OBJ_TYPE": "HOST", "UUID": host["UUID"], "HOST_IP": host["IP"], "BOARD_SERIAL": host["BOARD_SERIAL"], "URN": host["URN"]})
                cluster["CONTAIN_HOST"] = rel_host
                datastores = cluster["DATASTORE"]
                for datastore in datastores:
                    datastore_hosts = datastore["HOSTS"]
                    datastore_rel_host = []
                    for datastore_host_urn in datastore_hosts:
                        for host in hosts:
                            if host["URN"] == datastore_host_urn:
                                datastore_rel_host.append({"_OBJ_CATEGORY": "HOST", "_OBJ_TYPE": "HOST", "UUID": host["UUID"], "HOST_IP": host["IP"], "BOARD_SERIAL": host["BOARD_SERIAL"], "URN": host["URN"]})
                    datastore["REL_HOSTS"] = datastore_rel_host

                rel_vms = []
                for vm in vms:
                    if host["CLUSTERNAME"] == cluster["NAME"]:
                        vm["CLUSTERED_ON"] = [{"_OBJ_CATEGORY": "VIRTUALIZED", "_OBJ_CATEGORY": "VIRTUALIZED-CLUSTER", "MOID": cluster["MOID"], "NAME": cluster["NAME"], "URN": cluster["URN"]}]
                        vm["_OBJ_CATEGORY"] = "OS"
                        vm["_OBJ_TYPE"] = vm["OS_TYPE"]
                        vm["MGMT_IP"] = vm["IP"]
                        vm["test"] = "test"
                        rel_vms.append(vm)
                        # rel_vms.append({'_OBJ_CATEGORY': 'OS', '_OBJ_TYPE': vm['OS_TYPE'], 'MGMT_IP': vm['IP'], 'VM_ID': vm['VM_ID'],'NAME': vm['NAME'], 'UUID': vm['UUID'], 'STATUS': vm['STATUS'], 'HOST_ON': vm['HOST_ON']})
                # cluster['CONTAIN_VMS'] = rel_vms
                cluster["CONTAIN_VMS"] = rel_vms
            newsites.append(site)

            # 告警
            self.getAlarms(uri, alarms)

        data["DATACENTER"] = newsites
        data["ALARMS"] = alarms

        datas.append(data)
        return datas


def usage():
    pname = os.path.basename(__file__)
    print(pname + " --ip <manage ip> --user <user> --password <password> ")
    exit(1)


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--ip", default="", help="管理IP")
    parser.add_argument("--port", default="7443", help="API端口")
    parser.add_argument("--mgmt_port", default="8443", help="管理端口")
    parser.add_argument("--user", default="", help="vcenter console login user")
    parser.add_argument("--password", default="", help="vcenter console login user password")
    parser.add_argument("--verbose", default="0", help="verbose output")
    args = parser.parse_args()

    ip = args.ip
    user = args.user
    password = args.password
    port = args.port
    mgmt_port = args.mgmt_port
    isVerbose = int(args.verbose)
    node = os.getenv("AUTOEXEC_NODE")
    if node != None and node != "":
        node = json.loads(node)

    if (ip == None or ip == "" or user == None or user == "" or password == None or password == "") and (node == None or node == ""):
        usage()

    if (ip == None or ip == "" or user == None or user == "" or password == "" or password == None) and node != None:
        ip = node["host"]
        port = node["port"]
        if port is None or port == "":
            port = node["protocolPort"]
        user = node["username"]
        password = node["password"]

    fus = FusionComputer(ip, port, mgmt_port, user, password, isVerbose)
    datas = fus.collect()

    out = {}
    out["DATA"] = datas
    AutoExecUtils.saveOutput(out)

    if isVerbose == 1:
        print("==================\n")
        print(json.dumps(datas))
        print("==================\n")
